package com.huawei.hwclouds.lubanops.demo.common.util;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.apache.commons.lang3.StringUtils;

import com.huawei.hwclouds.lubanops.demo.common.exception.common.InternalErrorException;
import com.huawei.seccomponent.crypt.CryptoAPI;

/**
 * 采用scc实现加解密的接口
 *
 * @author y00438022
 * @since 2020/4/24
 **/
public class SCCEncryptUtil {

    private final static CryptoAPI SCC_API = new CryptoAPI();

    static {
        try {
            String deploymanSccConf = findSccConfigFilePath();
            SCC_API.initialize(deploymanSccConf);

        } catch (Exception e) {
            throw new InternalErrorException("failed to init scc ", e);
        }
    }

    /**
     * 获取scc配置文件的路径
     *
     * @return
     */
    private static String findSccConfigFilePath() {

        //在现网首先根据环境变量传进来的
        String deploymanSccConfigPath = System.getProperty("deployman.scc.config.path");

        if (!StringUtils.isBlank(deploymanSccConfigPath)) {
            if (!deploymanSccConfigPath.endsWith("/")) {
                deploymanSccConfigPath = deploymanSccConfigPath + "/";
            }
            deploymanSccConfigPath = StringUtil.clearString(deploymanSccConfigPath);
            String deploymanSccConf = deploymanSccConfigPath + "scc.conf";
            Path path = Paths.get(deploymanSccConf);
            boolean exists = Files.exists(path);
            System.out.println("file exists:" + exists + ",path:" + path);
            if (!exists) {
                throw new InternalErrorException(
                    "scc files specified in deployman.scc.config.path not exists:" + deploymanSccConf);
            }
            return deploymanSccConf;
        }

        //linux环境下生效
        deploymanSccConfigPath = "scc.conf";
        boolean exists = Files.exists(Paths.get(deploymanSccConfigPath));
        if (exists) {
            return deploymanSccConfigPath;
        }

        //测试环境
        deploymanSccConfigPath = "common/src/main/resources/scc.conf";
        exists = Files.exists(Paths.get(deploymanSccConfigPath));
        if (exists) {
            return deploymanSccConfigPath;
        }

        /**
         * 最后从classpath里面获取
         */
        URL url = SCCEncryptUtil.class.getClassLoader().getResource("scc.conf");
        if (url == null) {
            throw new InternalErrorException("could not find scc.conf");
        }

        try {
            File file = new File(url.toURI());

            deploymanSccConfigPath = file.getCanonicalPath();
            exists = Files.exists(Paths.get(deploymanSccConfigPath));
            if (exists) {
                return deploymanSccConfigPath;
            } else {
                throw new InternalErrorException("path " + deploymanSccConfigPath + " not exists");
            }

        } catch (URISyntaxException e) {
            throw new InternalErrorException("URISyntaxException is null", e);
        } catch (IOException e) {
            throw new InternalErrorException("IOException is null", e);
        }

    }


    /**
     * 实现加密
     *
     * @param inputStr 要加密的字段
     * @return
     */
    public static String encrypt(String inputStr) {
        try {
            return SCC_API.encrypt(inputStr);
        } catch (Exception e) {
            throw new InternalErrorException("failed to encrypt ", e);
        }
    }

    /**
     * 实现解密
     *
     * @param inputStr
     * @return
     */
    public static String decrypt(String inputStr) {
        try {
            return SCC_API.decrypt(inputStr).getString();
        } catch (Exception e) {
            throw new InternalErrorException("failed to decrypt ", e);
        }
    }


    public static void activeNewKey() {
        try {
            SCC_API.activeNewKey();
        } catch (Exception e) {
            throw new InternalErrorException("failed to activeNewKey ", e);
        }
    }

    public static String reEncrypt(String s) {
        try {
            return SCC_API.reEncrypt(s);
        } catch (Exception e) {
            throw new InternalErrorException("failed to reEncrypt ", e);
        }
    }

}
